<?php

/*
 * PDO wrapper
 *
 */
class Sqlexecutor
{
    private $_dbh = null;
    private $_host;
    private $_userName;
    private $_password;
    private $_dbName;
    private $_persistent;
    private $_port;

    public function __construct($host, $userName, $password, $dbName="", $persistent = true, $port = 3306)
    {
        $this->_host = $host;
        $this->_userName = $userName;
        $this->_password = $password;
        $this->_dbName = $dbName;
        $this->_persistent = $persistent;

        $dsn = "mysql:host=$host;port=$port";
        if($dbName)
        {
            $dsn = "mysql:host=$host;dbname=$dbName;port=$port";
        }
        $this->_logger = null;
        $this->_dbh = new PDO($dsn,
                              $userName,
                              $password,
                              array(PDO::ATTR_PERSISTENT => $persistent)
                             );
        $this->_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->_dbh->query("SET character_set_client=binary");
        $this->setVerbosity(false);
        $this->_dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
    }

    public function isConnection()
    {
        $status = $this->_dbh->getAttribute(PDO::ATTR_SERVER_INFO);

        return $status;
    }

    public function reConnect()
    {
        unset($this->_dbh);
    }

    public function selectDb($dbName)
    {
        $this->_dbh->query("use $dbName");
    }

    public function setVariables($name, $value)
    {
        $this->_dbh->query("SET $name = $value");
    }

    public function setNames($enc = 'utf8')
    {
        $this->_dbh->query("SET NAMES $enc");
    }

    public function setLogger($logger)
    {
        $this->_logger = $logger;
    }

	public function query($sql, $values=array())
	{
        $this->log($sql, $values);
        try {
            if(empty($values))
            {
                $sth = $this->_dbh->query($sql);
                return $sth->fetch(PDO::FETCH_ASSOC);
            }

            $sth = $this->_dbh->prepare($sql);
            $i = 0;
            foreach($values as $value)
            {
                $sth->bindValue(++$i, $value);
            }
            if($sth->execute())
            {
                return $sth->fetch(PDO::FETCH_ASSOC);
            }
        }
        catch (PDOException $e)
        {
            $this->processError($sql, $e);
            throw $e;
        }

        return false;
	}

	public function querys($sql, $values=array())
	{
        $this->log($sql, $values);
        try {
            if(empty($values))
            {
                $sth = $this->_dbh->query($sql);
                return $sth->fetchAll(PDO::FETCH_ASSOC);
            }

            $sth = $this->_dbh->prepare($sql);
            $i = 0;
            foreach($values as $value)
            {
                $sth->bindValue(++$i, $value);
            }
            if($sth->execute())
            {
                return $sth->fetchAll(PDO::FETCH_ASSOC);
            }
        }
        catch (PDOException $e)
        {
            $this->processError($sql, $e);
            throw $e;
        }
	}

	public function exeNoQuery($sql, $values=array())
    {
        $this->log($sql, $values);
        try {
            if(empty($values))
            {
                $cnt = $this->_dbh->exec($sql);
                return !($cnt === false);
            }

            $sth = $this->_dbh->prepare($sql);
            $i = 0;
            foreach($values as $value)
            {
                $sth->bindValue(++$i, $value);
            }
            return $sth->execute();
        }
        catch (PDOException $e)
        {
            $this->processError($sql, $e);
            throw $e;
        }
    }

    public function execute($sql, $values=array())
    {
        $this->log($sql, $values);
        try {
            if(empty($values))
            {
                return $this->_dbh->exec($sql);
            }

            $sth = $this->_dbh->prepare($sql);
            $i = 0;
            foreach($values as $value)
            {
                $sth->bindValue(++$i, $value);
            }
            $sth->execute();
            return $sth->rowCount();
        }
        catch (PDOException $e)
        {
            $this->processError($sql, $e);
            throw $e;
        }
    }

	public function beginTrans()
	{
        $this->_dbh->beginTransaction();
	}

	public function commit()
	{
        return $this->_dbh->commit();
	}

	public function rollback()
	{
        return $this->_dbh->rollback();
	}

    public function getLastInsertID()
    {
        return (int)$this->_dbh->lastInsertId();
    }

    private function log($sql, $values)
    {
        if($this->_logger != null)
        {
            $$this->_logger->debug($sql);
            if(!empty($values))
                $this->_logger->debug($values);
        }
    }

    public function setVerbosity($flag)
    {
        $this->_verbosity = $flag;
    }

    private function processError($sql, $e)
    {
        if($this->_verbosity)
        {
            echo $sql."\n";
            echo $e->getMessage();
            echo $e->getTraceAsString();
        }
    }
}

